package com.feiyuan.core.aspect;

import com.feiyuan.common.utils.ObjectMapperUtils;
import com.feiyuan.core.annotation.FeiyuanRequiresPermissions;
import com.feiyuan.core.pojo.entity.AdminUser;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 权限鉴定切面，需要在后端的每一个服务的启动类上面导入此类
 * @author Xupf
 * @datetime 2022-04-15 17:21:13
 */
@Aspect
@Component
public class PermissionsAspect {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Pointcut("@annotation(com.feiyuan.core.annotation.FeiyuanRequiresPermissions)")
    public void permissions(){}

    @Around("permissions()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        FeiyuanRequiresPermissions annotation = method.getAnnotation(FeiyuanRequiresPermissions.class);
        String permission = annotation.value();
        // 进行鉴权
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        String token = request.getHeader("ADMIN_TOKEN");
        String str = redisTemplate.opsForValue().get("ADMIN_USER_" + token);
        AdminUser adminUser = ObjectMapperUtils.readValue(str, AdminUser.class);
        List<String> perms = adminUser.getPerms();
        if (perms == null) {
            logger.error("this user is not permissions,so don`t pass!");
            out(response, "您没有权限!");
            return null;
        }
        // 如果为系统管理员的话，则直接放过，不用进行权限校验
        if (perms.get(0).equals("*")) {
            return joinPoint.proceed();
        }
        if (!perms.contains(permission)) {
            logger.error("user is not " + permission);
            out(response, "您没有此权限，不能使用!");
            return null;
        }
        return joinPoint.proceed();
    }

    /**
     * 没有权限或者出错后的返回
     * @param response
     * @param msg
     */
    private void out(HttpServletResponse response, String msg){
        try {
            Map<String, Object> message = new HashMap<>();
            ObjectMapper objectMapper = new ObjectMapper();
            message.put("code", 29500);
            message.put("message", msg);
            ServletOutputStream outputStream = response.getOutputStream();
            response.setContentType("text/html;charest=UTF-8");//设置页面显示编码格式和设置输出流编码格式
            outputStream.write(objectMapper.writeValueAsString(message).getBytes("UTF-8"));//输出到web客户端
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}
